package cn.lg.soar.common.data;

import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Stream;

/**
 * 有序set集合
 * @author luguoxiang
 * @date 2022/3/30
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class ZSet<E> implements Set<E>, Cloneable, java.io.Serializable {

    private Map<E, Integer> map;

    public ZSet(Collection<? extends E> c, int order) {
        map = new HashMap<>();
        this.addAll(c, order);
    }

    public ZSet(Collection<? extends E> c) {
        map = new HashMap<>();
        this.addAll(c);
    }

    public ZSet() {
        map = new HashMap<>();
    }

    public ZSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    public ZSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    @Override
    public Iterator<E> iterator() {
        return stream().iterator();
    }

    @Override
    public Stream<E> stream() {
        return map.entrySet()
                .stream()
                .sorted((a, b) -> a.getValue() - b.getValue())
                .map(Map.Entry::getKey);
    }

    @Override
    public void forEach(Consumer<? super E> action) {
        map.entrySet()
                .stream()
                .sorted((a, b) -> a.getValue() - b.getValue())
                .forEach(x -> action.accept(x.getKey()));
    }

    @Override
    public Object[] toArray() {
        return stream().toArray();
    }

    @Override
    public <T> T[] toArray(T[] at) {
        T[] finalAt = at;
        return stream().toArray(len -> finalAt);
    }

    public boolean add(E e, int order) {
        map.put(e, order);
        return true;
    }

    @Override
    public boolean add(E e) {
        return add(e, 0);
    }

    public boolean addAll(Collection<? extends E> c, int order) {
        if (c == null) {
            return false;
        }
        c.forEach(x -> map.put(x, order));
        return true;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return addAll(c, 0);
    }

    @Override
    public int size() {
        return map.size();
    }

    @Override
    public boolean isEmpty() {
        return map.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return map.containsValue(o);
    }

    @Override
    public boolean remove(Object o) {
        map.remove(o);
        return true;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return map.keySet().containsAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return map.keySet().retainAll(c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        if (c == null) {
            return false;
        }
        c.forEach(x -> map.remove(x));
        return true;
    }

    @Override
    public void clear() {
        map.clear();
    }
}
